package edu.winona.csclub.testing.generators;

import java.util.*;

import edu.winona.csclub.testing.core.*;

/**
 * Uses worst case analysis methods to generate test cases
 * <p><b>Normal (5^n)</b>: cartesian product of the min, min+, nom, max-, and max of every variable
 * <br><b>Robust (7^n)</b>: cartesian product of the min-, min, min+, nom, max-, max, and max+ of every variable
 * 
 * @author Matthew Lieder
 */
public class WorstCase implements EnumProvider {
	
	private boolean robust = false;
	
	/**
	 * Creates a new WorstCase instance using Normal or Robust WCA
	 */	
	public WorstCase(boolean robust) {
		this.robust = robust;
	}

	public void generateTests(Command command, TestCase tests) {
		generateTests(command, tests, new LinkedList<Value>());
	}
	
	/**
	 * Generates tests by recursively filling in the values list,
	 * creating a test whenever the list fills up
	 */
	private void generateTests(Command command, TestCase tests, List<Value> values) {
		// get the next variable that doesn't have its values generated yet
		Variable var = command.getVariables().get(values.size());
		List<Value> singleVarValues = new LinkedList<Value>();
		
		// generate all the different values to test this variable with
		if(robust) singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMin() - 1))); // min-
		singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMin()))); // min
		singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMin() + 1))); // min+
		singleVarValues.add(new Value(var, "" + (var.getRange()[0].getNom()))); // nom
		singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMax() - 1))); // max-
		singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMax()))); // max
		if(robust) singleVarValues.add(new Value(var, "" + (var.getRange()[0].getMax() + 1))); // max+
		
		// generate test cases using those generated values for this variable
		// using recursion if all variables haven't supplied values yet for this test
		for(Value val: singleVarValues) {
			List<Value> newValues = new LinkedList<Value>(values);
			newValues.add(val);
			
			if(newValues.size() < command.getVariables().size())
				generateTests(command, tests, newValues);
			else
				tests.addTest(new Test(command, newValues));
		}
	}
}